home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / M_bigmech.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-12-07  |  11.8 KB  |  526 lines

  1. /*
  2. ==============================================================================
  3.  
  4. BOSS MECH
  5.  
  6. ==============================================================================
  7. */
  8.  
  9. #include "g_local.h"
  10. #include "M_bigmech.h"
  11.  
  12.  
  13. void boss_doattack_rocket (edict_t *self);
  14.  
  15. static int    sound_thud;
  16. static int    sound_pain;
  17. static int    sound_idle;
  18. static int    sound_die;
  19. static int    sound_step;
  20. static int    sound_sight;
  21. static int    sound_windup;
  22. static int    sound_strike;
  23. static int  sound_fire;
  24.  
  25. //
  26. // misc
  27. //
  28.  
  29. void boss_sight (edict_t *self, edict_t *other)
  30. {
  31.     gi.sound (self, CHAN_VOICE, sound_sight, 1, ATTN_NORM, 0);
  32. }
  33.  
  34. void boss_stomp_right (edict_t *self)
  35. {
  36.     int        i;
  37.     edict_t    *e;
  38.     vec3_t    forward, right;
  39.     vec3_t    start;
  40.  
  41.     for (i=1, e=g_edicts+i; i < globals.num_edicts; i++,e++)
  42.     {
  43.         if (!e->inuse)
  44.             continue;
  45.         if (!e->client)
  46.             continue;
  47.         if (!e->groundentity)
  48.             continue;
  49.  
  50.         e->groundentity = NULL;
  51.         e->velocity[0] += crandom()* 50;
  52.         e->velocity[1] += crandom()* 50;
  53.         e->velocity[2] += crandom()* 100;
  54.     }
  55.     
  56.     AngleVectors (self->s.angles, forward, right, NULL);
  57.     VectorCopy (self->s.origin, start);
  58.  
  59.     //start[2] = start[2] - 16;
  60.         
  61.     right[0] = right[0] * 25;
  62.     right[1] = right[1] * 25;
  63.     forward[0] = forward[0] * 10;
  64.     forward[1] = forward[1] * 10;
  65.  
  66.     VectorAdd(start, forward, start);
  67.     VectorAdd(start, right, start);
  68.  
  69.     gi.WriteByte (svc_temp_entity);
  70.     gi.WriteByte (TE_EXPLOSION2);
  71.     gi.WritePosition (start);
  72.     gi.multicast (start, MULTICAST_PVS);
  73.  
  74.     gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0);
  75. }
  76.  
  77. void boss_stomp_left (edict_t *self)
  78. {
  79.     int        i;
  80.     edict_t    *e;
  81.     vec3_t    forward, right;
  82.     vec3_t    start;
  83.  
  84.     for (i=1, e=g_edicts+i; i < globals.num_edicts; i++,e++)
  85.     {
  86.         if (!e->inuse)
  87.             continue;
  88.         if (!e->client)
  89.             continue;
  90.         if (!e->groundentity)
  91.             continue;
  92.  
  93.         e->groundentity = NULL;
  94.         e->velocity[0] += crandom()* 50;
  95.         e->velocity[1] += crandom()* 50;
  96.         e->velocity[2] += crandom()* 100;
  97.     }
  98.     
  99.     AngleVectors (self->s.angles, forward, right, NULL);
  100.     VectorCopy (self->s.origin, start);
  101.     
  102. //    start[2] = start[2] - 16;
  103.     
  104.     right[0] = right[0] * -25;
  105.     right[1] = right[1] * -25;
  106.  
  107.     forward[0] = forward[0] * 10;
  108.     forward[1] = forward[1] * 10;
  109.  
  110.     VectorAdd(start, forward, start);
  111.     
  112.     VectorAdd(start, right, start);
  113.  
  114.     gi.WriteByte (svc_temp_entity);
  115.     gi.WriteByte (TE_EXPLOSION2);
  116.     gi.WritePosition (start);
  117.     gi.multicast (start, MULTICAST_PVS);
  118.  
  119.     gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0);
  120. }
  121.  
  122. void boss_thud (edict_t *self)
  123. {
  124.     gi.sound (self, CHAN_VOICE, sound_thud, 1, ATTN_NORM, 0);
  125. }
  126.  
  127. void boss_windup (edict_t *self)
  128. {
  129.     gi.sound (self, CHAN_VOICE, sound_windup, 1, ATTN_NORM, 0);
  130. }
  131.  
  132. void boss_idle (edict_t *self)
  133. {
  134.     gi.sound (self, CHAN_VOICE, sound_idle, 1, ATTN_IDLE, 0);
  135. }
  136.  
  137.  
  138. //
  139. // stand
  140. //
  141.  
  142. mframe_t boss_frames_stand []=
  143. {
  144.     ai_stand, 0, NULL,
  145.     ai_stand, 0, NULL,
  146.     ai_stand, 0, NULL,
  147.     ai_stand, 0, NULL,
  148.     ai_stand, 0, NULL,
  149.     ai_stand, 0, NULL,
  150.     ai_stand, 0, NULL,
  151. };
  152. mmove_t    boss_move_stand = {FRAME_shoot01, FRAME_shoot07, boss_frames_stand, NULL};
  153.     
  154. void boss_stand (edict_t *self)
  155. {
  156.     self->monsterinfo.currentmove = &boss_move_stand;
  157. }
  158.  
  159.  
  160. //
  161. // walk
  162. //
  163.  
  164. void boss_walk (edict_t *self);
  165.  
  166.  
  167. mframe_t boss_frames_walk [] =
  168. {
  169.     ai_walk, 14,    boss_stomp_left,
  170.     ai_walk, 15,    NULL,
  171.     ai_walk, 13,    NULL,
  172.     ai_walk, 12,    NULL,
  173.     ai_walk, 0,        NULL,
  174.     ai_walk, 0,        NULL,
  175.     ai_walk, 0,        boss_stomp_right,
  176.     ai_walk, 13,    NULL,
  177.     ai_walk, 15,    NULL,
  178.     ai_walk, 17,    NULL,
  179.     ai_walk, 0,        NULL,
  180.     ai_walk, 0,        NULL
  181. };
  182. mmove_t    boss_move_walk = {FRAME_walk01, FRAME_walk12, boss_frames_walk, NULL};
  183.  
  184. void boss_walk (edict_t *self)
  185. {
  186.     self->monsterinfo.currentmove = &boss_move_walk;
  187. }
  188.  
  189.  
  190. //
  191. // run
  192. //
  193.  
  194. void boss_run (edict_t *self);
  195.  
  196. mframe_t boss_frames_run [] =
  197. {
  198.     ai_run, 14,    boss_stomp_left,
  199.     ai_run, 15,    NULL,
  200.     ai_run, 13,    NULL,
  201.     ai_run, 12,    NULL,
  202.     ai_run, 0,    NULL,
  203.     ai_run, 0,    NULL,
  204.     ai_run, 0,    boss_stomp_right,
  205.     ai_run, 13,    NULL,
  206.     ai_run, 15,    NULL,
  207.     ai_run, 17,    NULL,
  208.     ai_run, 0,    NULL,
  209.     ai_run, 0,    NULL
  210. };
  211. mmove_t    boss_move_run = {FRAME_walk01, FRAME_walk12, boss_frames_run, NULL};
  212.  
  213. void boss_run (edict_t *self)
  214. {
  215.     if (self->enemy && self->enemy->client)
  216.         self->monsterinfo.aiflags |= AI_BRUTAL;
  217.     else
  218.         self->monsterinfo.aiflags &= ~AI_BRUTAL;
  219.  
  220.     if (self->monsterinfo.aiflags & AI_STAND_GROUND)
  221.     {
  222.         self->monsterinfo.currentmove = &boss_move_stand;
  223.         return;
  224.     }
  225.  
  226.     self->monsterinfo.currentmove = &boss_move_run;
  227. }
  228.  
  229. //
  230. // pain
  231. //
  232.  
  233. mframe_t boss_frames_pain1 [] =
  234. {
  235.     ai_move, 0, NULL,
  236.     ai_move, 0, NULL,
  237.     ai_move, 0, NULL,
  238.     ai_move, 0, NULL
  239. };
  240. mmove_t boss_move_pain1 = {FRAME_shoot01, FRAME_shoot04, boss_frames_pain1, boss_run};
  241.  
  242. mframe_t boss_frames_pain2 [] =
  243. {
  244.     ai_move, 0, NULL,
  245.     ai_move, 0, NULL,
  246.     ai_move, 0, NULL,
  247.     ai_move, 0, NULL,
  248.     ai_move, 0, NULL
  249. };
  250. mmove_t boss_move_pain2 = {FRAME_shoot01, FRAME_shoot05, boss_frames_pain2, boss_run};
  251.  
  252. mframe_t boss_frames_pain3 [] =
  253. {
  254.     ai_move, -7, NULL,
  255.     ai_move, 0,  NULL,
  256.     ai_move, 0,  NULL,
  257.     ai_move, 0,  NULL,
  258.     ai_move, 2,  NULL,
  259.     ai_move, 0,  NULL,
  260. };
  261. mmove_t    boss_move_pain3 = {FRAME_shoot01, FRAME_shoot06, boss_frames_pain3, boss_run};
  262.  
  263.  
  264. void boss_pain (edict_t *self, edict_t *other, float kick, int damage)
  265. {
  266.     if (self->health < (self->max_health / 2))
  267.             self->s.skinnum |= 1;
  268.  
  269.     if (damage <= 10)
  270.         return;
  271.  
  272.     if (level.time < self->pain_debounce_time)
  273.             return;
  274.  
  275.     if (damage <= 30)
  276.         if (random() > 0.2)
  277.             return;
  278.     
  279.     // If hard or nightmare, don't go into pain while attacking
  280.  
  281.     self->pain_debounce_time = level.time + 3;
  282.     gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
  283.  
  284.     if (damage <= 30)
  285.         self->monsterinfo.currentmove = &boss_move_pain1;
  286.     else if (damage <= 60)
  287.         self->monsterinfo.currentmove = &boss_move_pain2;
  288.     else
  289.         self->monsterinfo.currentmove = &boss_move_pain3;
  290. }
  291.  
  292.  
  293. //
  294. // attacks
  295. //
  296.  
  297. void bossStrike (edict_t *self)
  298. {
  299.     gi.sound (self, CHAN_WEAPON, sound_strike, 1, ATTN_NORM, 0);
  300. }    
  301.  
  302. void bossRocket1 (edict_t *self)
  303. {
  304.     vec3_t    forward, right;
  305.     vec3_t    start;
  306.     vec3_t    dir;
  307.     vec3_t    vec;
  308.     int        flash_number;
  309.  
  310.     flash_number = MZ2_TANK_ROCKET_3;
  311.  
  312.     AngleVectors (self->s.angles, forward, right, NULL);
  313.  
  314.     right[0] = right[0] * 2.7;
  315.     right[1] = right[1] * 2.7;
  316.  
  317.     G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
  318.     
  319.     VectorCopy (self->enemy->s.origin, vec);
  320.     vec[2] += self->enemy->viewheight;
  321.     VectorSubtract (vec, start, dir);
  322.     VectorNormalize (dir);
  323.     start[2] = start[2] - 4;
  324.     gi.sound (self, CHAN_VOICE, sound_fire, 1, ATTN_NORM, 0);
  325.  
  326.     gi.WriteByte (svc_temp_entity);
  327.     gi.WriteByte (TE_EXPLOSION1);
  328.     gi.WritePosition (start);
  329.     gi.multicast (start, MULTICAST_PVS);
  330.  
  331.     monster_fire_rocket (self, start, dir, 50, 550, flash_number);
  332. }    
  333.  
  334. void bossRocket2 (edict_t *self)
  335. {
  336.     vec3_t    forward, right;
  337.     vec3_t    start;
  338.     vec3_t    dir;
  339.     vec3_t    vec;
  340.     int        flash_number;
  341.  
  342.     flash_number = MZ2_TANK_ROCKET_3;
  343.  
  344.     AngleVectors (self->s.angles, forward, right, NULL);
  345.  
  346.     right[0] = right[0] * -2.7;
  347.     right[1] = right[1] * -2.7;
  348.  
  349.     G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
  350.     
  351.     VectorCopy (self->enemy->s.origin, vec);
  352.     vec[2] += self->enemy->viewheight;
  353.     VectorSubtract (vec, start, dir);
  354.     VectorNormalize (dir);
  355.     start[2] = start[2] - 8;
  356.     gi.sound (self, CHAN_VOICE, sound_fire, 1, ATTN_NORM, 0);
  357.  
  358.     gi.WriteByte (svc_temp_entity);
  359.     gi.WriteByte (TE_EXPLOSION1);
  360.     gi.WritePosition (start);
  361.     gi.multicast (start, MULTICAST_PVS);
  362.  
  363.     monster_fire_rocket (self, start, dir, 50, 550, flash_number);
  364. }
  365.  
  366. mframe_t boss_frames_attack_fire_rocket [] =
  367. {
  368.     ai_charge, -3, NULL,        // Loop Start    22 
  369.     ai_charge, 0,  NULL,
  370.     ai_charge, 0,  NULL,
  371.     ai_charge, 0,  bossRocket1,
  372.     ai_charge, 0,  bossRocket2,
  373.     ai_charge, 0,  NULL,
  374.     ai_charge, -1, NULL            // 30    Loop End
  375. };
  376. mmove_t boss_move_attack_fire_rocket = {FRAME_shoot01, FRAME_shoot07, boss_frames_attack_fire_rocket, boss_run};
  377.  
  378. void boss_doattack_rocket (edict_t *self)
  379. {
  380.     self->monsterinfo.currentmove = &boss_move_attack_fire_rocket;
  381. }
  382.  
  383. void boss_attack (edict_t *self)
  384. {
  385.     vec3_t    vec;
  386.     float    range;
  387.     float    r;
  388.  
  389.     VectorSubtract (self->enemy->s.origin, self->s.origin, vec);
  390.     range = VectorLength (vec);
  391.  
  392.     r = random();
  393.  
  394.     self->monsterinfo.currentmove = &boss_move_attack_fire_rocket;
  395.     self->pain_debounce_time = level.time + 5.0;    // no pain for a while
  396. }
  397.  
  398.  
  399. //
  400. // death
  401. //
  402.  
  403. void boss_dead (edict_t *self)
  404. {
  405.     VectorSet (self->mins, -16, -16, -56);
  406.     VectorSet (self->maxs, 16, 16, -8);
  407.     self->movetype = MOVETYPE_TOSS;
  408.     self->svflags |= SVF_DEADMONSTER;
  409.     self->nextthink = 0;
  410.     gi.linkentity (self);
  411. }
  412.  
  413. mframe_t boss_frames_death1 [] =
  414. {
  415.     ai_move, 0,  NULL,
  416.     ai_move, 0,  NULL,
  417.     ai_move, 0,  NULL,
  418.     ai_move, 0,  NULL,
  419.     ai_move, 0,  NULL,
  420.     ai_move, 0,  NULL
  421. };
  422. mmove_t    boss_move_death = {FRAME_shoot01, FRAME_shoot06, boss_frames_death1, boss_dead};
  423.  
  424. void boss_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  425. {    
  426.     int        n, spd;
  427.     vec3_t start, org;
  428.  
  429.     // tower of fire code here (will add body parts flying next)
  430.     VectorCopy (self->s.origin, start);
  431.     for (n = 1; n < 3; n++)
  432.     {
  433.         start[2] = start[2] + 64;
  434.         gi.WriteByte (svc_temp_entity);
  435.         gi.WriteByte (TE_EXPLOSION1);
  436.         gi.WritePosition (start);
  437.         gi.multicast (start, MULTICAST_PVS);
  438.     }
  439.  
  440.     for (n = 0; n < 3; n++)
  441.     {
  442.         spd = 5;
  443.         org[0] = self->s.origin[0] + crandom() * 5.0;
  444.         org[1] = self->s.origin[1] + crandom() * 5.0;
  445.         org[2] = self->s.origin[2] + crandom() * 5.0;
  446.         ThrowDebris (self, "models/objects/gibs/bigmech_arm/tris.md2", spd, org);
  447.     }
  448.  
  449.     ThrowHead (self, "models/objects/gibs/bigmech_bod/tris.md2", damage, GIB_METALLIC, EF_GIB);
  450.  
  451.     self->deadflag = DEAD_DEAD;
  452.     self->takedamage = DAMAGE_NO;
  453.     VectorSet (self->mins, -32, -32, 0);
  454.     VectorSet (self->maxs, 32, 32, 8);
  455.     self->movetype = MOVETYPE_TOSS;
  456.     self->nextthink = 0;
  457.     self->think = NULL;
  458. }
  459.  
  460.  
  461. //
  462. // monster_boss
  463. //
  464.  
  465. /*QUAKED monster_boss (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight
  466. */
  467. /*QUAKED monster_boss_commander (1 .5 0) (-32 -32 -16) (32 32 72) Ambush Trigger_Spawn Sight
  468. */
  469. void SP_monster_bigmech (edict_t *self)
  470. {
  471.     if (deathmatch->value)
  472.     {
  473.         G_FreeEdict (self);
  474.         return;
  475.     }
  476.  
  477.     self->s.modelindex = gi.modelindex ("models/monsters/bigmech/tris.md2");
  478.     VectorSet (self->mins, -64, -64, 0);
  479.     VectorSet (self->maxs, 64, 64, 128);
  480.     self->movetype = MOVETYPE_STEP;
  481.     self->solid = SOLID_BBOX;
  482.  
  483.     sound_pain = gi.soundindex ("robot9/move1.wav");
  484.     sound_thud = gi.soundindex ("martian/step.wav");
  485.     sound_idle = gi.soundindex ("robot9/mach.wav");
  486.     sound_die = gi.soundindex ("martian/step.wav");
  487.     sound_step = gi.soundindex ("robot9/servo2.wav");
  488.     sound_windup = gi.soundindex ("robot9/servo2.wav");
  489.     sound_strike = gi.soundindex ("robot9/mach.wav");
  490.     sound_sight = gi.soundindex ("robot9/move3.wav");
  491.     sound_fire = gi.soundindex ("weapons/rocklf1a.wav");
  492.  
  493.     gi.soundindex ("tank/tnkatck1.wav");
  494.     gi.soundindex ("tank/tnkatk2a.wav");
  495.     gi.soundindex ("tank/tnkatk2b.wav");
  496.     gi.soundindex ("tank/tnkatk2c.wav");
  497.     gi.soundindex ("tank/tnkatk2d.wav");
  498.     gi.soundindex ("tank/tnkatk2e.wav");
  499.     gi.soundindex ("tank/tnkatck3.wav");
  500.  
  501.     self->max_health = 750;
  502.     self->health = self->max_health;
  503.     self->gib_health = -200;
  504.     
  505.     self->mass = 500;
  506.     self->classname = "monster_mech";
  507.  
  508.     self->pain = boss_pain;
  509.     self->die = boss_die;
  510.     self->monsterinfo.stand = boss_stand;
  511.     self->monsterinfo.walk = boss_walk;
  512.     self->monsterinfo.run = boss_run;
  513.     self->monsterinfo.dodge = NULL;
  514.     self->monsterinfo.attack = boss_attack;
  515.     self->monsterinfo.melee = NULL;
  516.     self->monsterinfo.sight = boss_sight;
  517.     self->monsterinfo.idle = boss_idle;
  518.  
  519.     gi.linkentity (self);
  520.     
  521.     self->monsterinfo.currentmove = &boss_move_stand;
  522.     self->monsterinfo.scale = MODEL_SCALE;
  523.  
  524.     walkmonster_start (self);
  525. }
  526.